package cc.shacocloud.mirage.restful.bind.support;

import cc.shacocloud.mirage.restful.HttpRequest;
import cc.shacocloud.mirage.restful.HttpResponse;
import cc.shacocloud.mirage.restful.VertxInvokeHandler;
import cc.shacocloud.mirage.restful.http.MediaType;
import cc.shacocloud.mirage.utils.comparator.Ordered;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import org.jetbrains.annotations.NotNull;

import java.util.List;

/**
 * 返回 json 格式处理器
 *
 * @author 思追(shaco)
 */
public class JsonHandlerExceptionResolver extends AbstractDefaultHandlerExceptionResolver {
    
    private final ObjectMapper objectMapper;
    
    public JsonHandlerExceptionResolver(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    
    /**
     * 结果模板返回 application/json 格式内容
     */
    @Override
    protected boolean shouldApplyTo(@NotNull HttpRequest request, @NotNull VertxInvokeHandler handler) {
        List<MediaType> mediaTypes = request.headers().getAcceptableMediaTypes();
        for (MediaType mediaType : mediaTypes) {
            if (mediaType.isCompatibleWith(MediaType.APPLICATION_JSON)) {
                return true;
            }
        }
        return false;
    }
    
    @Override
    protected Future<Buffer> doResolveException(@NotNull HttpRequest request,
                                                @NotNull HttpResponse response,
                                                @NotNull VertxInvokeHandler handler,
                                                @NotNull Throwable cause,
                                                @NotNull DefaultExceptionMo defaultExceptionMo) {
        response.headers().setContentType(MediaType.APPLICATION_JSON);
        try {
            Buffer buffer = Buffer.buffer(objectMapper.writeValueAsString(defaultExceptionMo));
            return Future.succeededFuture(buffer);
        } catch (JsonProcessingException e) {
            return Future.failedFuture(e);
        }
    }
    
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 1;
    }
}
